﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Windows.Forms;
using ALDIOrganizer.Properties;

namespace ALDIOrganizer
{
    public partial class MainForm
    {
        #region buttons' event handlers (Click event)
        private void btnAddHolidays_Click(object sender, EventArgs e)
        {
            AddHolidays((bool?)null);
        }

        private void btnAddPendingHoliday_Click(object sender, EventArgs e)
        {
            AddHolidays((bool?)true);
        }
        
        private void btnEditHolidays_Click(object sender, EventArgs e)
        {
            var selected = lvHolidays.SelectedItems;
            if (selected.Count == 0)
            {
                return;
            }
            EditHolidays(
                lvHolidays.SelectedTag.id,
                (bool?)null);
        }
        
        private void btnEditPendingHolidays_Click(object sender, EventArgs e)
        {
            var selected = lvHolidaysPending.SelectedItems;
            if (selected.Count == 0)
            {
                return;
            }
            EditHolidays(
                lvHolidaysPending.SelectedTag.id,
                (bool?)true);
        }

        private void btnAcceptPendingHolidays_Click(object sender, EventArgs e)
        {
            var userSure = MessageBox.Show(
                Resources.MESSAGEBOX_QUESTION_AcceptPendingHoliday_MESSAGE,
                Resources.MESSAGEBOX_QUESTION_AcceptPendingHoliday_CAPTION,
                MessageBoxButtons.YesNo,
                MessageBoxIcon.Question);
            if (userSure == DialogResult.No)
            {
                return;
            }
            SwitchPendingHoliday(false);
        }

        private void btnRejectPendingHolidays_Click(object sender, EventArgs e)
        {
            DeleteHolidays(lvHolidaysPending.SelectedTag.id);
        }

        private void btnDeleteHolidays_Click(object sender, EventArgs e)
        {
            DeleteHolidays(lvHolidays.SelectedTag.id);
        }
        #endregion

        void cbYear_SelectedValueChanged(object sender, EventArgs e)
        {
            lvHolidays_Populate();
            DataBind_sheetEmployeesHolidays();
        }

        private void DataBind_sheetEmployeesHolidays()
        {
            dgridHolidayEmployees.DataSource = EmployeeAllowance.GetDataSource(
                SQLiteAccess.EmployedInYear((int)cbYear.SelectedValue),
                (int)cbYear.SelectedValue);
        }


        private void DataBind_lvHolidays()
        {
            lvHolidays.SetColumnFillWeight(0, 20); // _employee
            lvHolidays.SetColumnFillWeight(1, 20); // period
            lvHolidays.SetColumnFillWeight(2, 15); // GetTotal days
            lvHolidays.SetColumnFillWeight(3, 15); // status
            lvHolidays.SetColumnFillWeight(4, 15); // MyCellType
            lvHolidays.SetColumnFillWeight(5, 15); // comments

            lvHolidaysPending.SetColumnFillWeight(0, 30); // _employee
            lvHolidaysPending.SetColumnFillWeight(1, 30); // period
            lvHolidaysPending.SetColumnFillWeight(2, 13); // GetTotal days
            lvHolidaysPending.SetColumnFillWeight(3, 13); // MyCellType
            lvHolidaysPending.SetColumnFillWeight(4, 0); // status
            lvHolidaysPending.SetColumnFillWeight(5, 13); // comments
            
            
            _holidayItems = new List<ListViewItem>();

            lvHolidays.IsEditable = new ImprovedListView.IsEditableDelegate(HolidayEditable);
            
            lvHolidays.OnWhenSelected.Add(btnEditHolidays);
            lvHolidays.OnWhenSelected.Add(btnDeleteHolidays);

            lvHolidaysPending.IsEditable = new ImprovedListView.IsEditableDelegate(PendingHolidayEditable);
            
            lvHolidaysPending.OnWhenSelected.Add(btnEditPendingHolidays);
            lvHolidaysPending.OnWhenSelected.Add(btnAcceptPendingHolidays);       
            lvHolidaysPending.OnWhenSelected.Add(btnRejectPendingHolidays);            

        }


        bool PendingHolidayEditable()
        {
            if (lvHolidaysPending.SelectedTag == null)
            {
                return false;
            }
            if (Program.Logged.CanEditHolidays |
                Program.Logged.CanEditPastHolidays)
            {
                return true;
            }
            
            return lvHolidaysPending.SelectedTag.employeeID == Program.Logged.ID;
        }
                
        private void lvHolidaysPending_Populate()
        {
            lvHolidaysPending.SuspendLayout();
            lvHolidaysPending.Items.Clear();
            var dvPendingHolidays = SQLiteAccess.GetHolidaysDataView(
                (int)cbYear.SelectedValue,
                -1,
                (bool?)true,
                (bool?)false);
            lvHolidaysPending.Items.AddRange((from DataRowView holiday
                                                  in dvPendingHolidays
                                              select holiday.AsListViewItem(false)).ToArray());
            lvHolidaysPending.ResumeLayout();
            lvHolidaysPending.TriggerOnSelectedIndexChanged();
        }


        /// <summary>
        /// populates (or re-populates) lvHolidays with all holidays
        /// </summary>
        private void lvHolidays_Populate()
        {            
            lvHolidays.SuspendLayout();

            lvHolidays.Items.Clear();
            _holidayItems.Clear();
            
            /* if "include pending" is checked On, all the holidays will be shown REGARDLESS of
             * whether or not they are pending. that'pShift why we are passing null.
             * 
             * if cbShowPending is checked off, we want to display only those holidays
             * whose "pending" field is FALSE. that'pShift why we are passing false.
             * 
             * if we passed (bool?)true, we'd display ONLY pending holidays. */
            Nullable<bool> pending = cbShowPending.Checked ? null : (bool?)false;
            /* same as above.
             * if cbShowFinished is checked On, we want to see all holidays whatsoever
             * (not "just" Complete ones, but all - Complete ones including */
            Nullable<bool> finished = cbShowFinished.Checked ? null : (bool?)false;

            _dvHolidays = SQLiteAccess.GetHolidaysDataView(
                (int)cbYear.SelectedValue,
                cbShowAll.Checked ? -1 : HolidaysTab_GetSelectedEmployeeID,
                pending,
                finished);

            foreach (DataRowView holiday in _dvHolidays)
            {
                _holidayItems.Add(holiday.AsListViewItem(true)); // TODO: user pParameters
            }


            SetAndAssignGroups();
            lvHolidays.Items.AddRange(_holidayItems.ToArray());
                        
            
            lvHolidays.ResumeLayout();                       
            lvHolidays.TriggerOnSelectedIndexChanged();
            
        }

        
        

        private void SetAndAssignGroups()
        {
            lvHolidays.ShowGroups = (GroupHolidaysBy != HolidaysGroupBy.None);

            var _columns_to_hide = new List<int>();
            switch (GroupHolidaysBy)
            {
                case HolidaysGroupBy.None:
                    {
                        break;
                    }
                case HolidaysGroupBy.ByPerson:
                    {
                        _columns_to_hide.Add(lvHolidays_emp.Index);
                        break;
                    }
                case HolidaysGroupBy.ByTimestatus:
                    {
                        _columns_to_hide.Add(lvHolidays_status.Index);
                        break;
                    }
                default: // = HolidaysGroupBy.ByMonth, since that's the only one left out
                    {
                        // and we don't need to hide any columns in that case
                        break;
                    }
            }
            lvHolidays.UnhideAllColumns();
            lvHolidays.HideColumns(_columns_to_hide.ToArray());
            lvHolidays.AutoSizeColumns();
            lvHolidaysPending.UnhideAllColumns();
            lvHolidaysPending.HideColumns(new[]
            {
                lvPendingHolidays_status.Index 
            });
            lvHolidaysPending.AutoSizeColumns();
            if (!lvHolidays.ShowGroups)
            {
                return;
            }
            lvHolidays.SuspendLayout();
            lvHolidays.Groups.Clear();
            
            #region building up the groups. we use Distinct queries to find out what groups are required
            IEnumerable<Int64> groups = null;
            if (GroupHolidaysBy == HolidaysGroupBy.ByPerson)
            {
                groups = (from item in _holidayItems
                          select ((ListViewItemTag) item.Tag).employeeID)
                          .Distinct();
            }

            if (GroupHolidaysBy == HolidaysGroupBy.ByMonth)
            {
                groups = (from item in _holidayItems
                          orderby ((ListViewItemTag) item.Tag).month
                          select ((ListViewItemTag) item.Tag).month)
                          .Distinct();
            }

            if (GroupHolidaysBy == HolidaysGroupBy.ByTimestatus)
            {
                groups = (from item in _holidayItems
                          orderby ((ListViewItemTag) item.Tag).timeStatus
                          select ((ListViewItemTag) item.Tag).timeStatus)
                          .Distinct();
            }

            if (groups == null)
            {
                return;
            }

            foreach (var i in groups)
            {
                var title = String.Empty;
                if (GroupHolidaysBy == HolidaysGroupBy.ByPerson)
                {
                    title = SQLiteAccess.GetEmployeeFirstName(i);
                }
                if (GroupHolidaysBy == HolidaysGroupBy.ByMonth)
                {
                    title = Program.CurrentCulture.DateTimeFormat.GetMonthName(Convert.ToInt32(i));
                }
                if (GroupHolidaysBy == HolidaysGroupBy.ByTimestatus)
                {
                    if (i == -1)
                    {
                        title = Resources.HOLIDAY_TimeStatus_Finished;
                    }
                    if (i == 0)
                    {
                        title = Resources.HOLIDAY_TimeStatus_InProgress;
                    }
                    if (i == 1)
                    {
                        title = Resources.HOLIDAY_TimeStatus_Ahead;
                    }
                }

                lvHolidays.Groups.Add(
                    i.ToString(),
                    title);
            }
            #endregion

            #region now we're actually assigning every listViewItem to an appropriate group
            foreach (var item in _holidayItems)
            {
                Int64 g;
                switch (GroupHolidaysBy)
                {
                    case HolidaysGroupBy.ByPerson:
                        {
                            g = ((ListViewItemTag) item.Tag).employeeID;
                            break;
                        }
                    case HolidaysGroupBy.ByTimestatus:
                        {
                            g = ((ListViewItemTag) item.Tag).timeStatus;
                            break;
                        }
                    case HolidaysGroupBy.ByMonth:
                        {
                            g = ((ListViewItemTag) item.Tag).month;
                            break;
                        }
                    default:
                        {
                            g = 0;
                            break;
                        }
                }
                item.Group = lvHolidays.Groups[g.ToString()];
            }
            #endregion                       

            lvHolidays.ResumeLayout();
        }




    }
}
